package doc

import (
	"errors"
	"gitee.com/dreamwood/jxgo/v1/core"
	"gitee.com/dreamwood/jxgo/v1/mgorm"
	"gitee.com/dreamwood/jxgo/v1/ss"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"time"
)

type Demo struct {
	Id       primitive.ObjectID `jx:"id" json:"id" bson:"_id,omitempty"`
	Name     string             `jx:"name" json:"name" bson:"name"`
	Age      int64              `jx:"age" json:"age" bson:"age"`
	Score    float64            `jx:"score" json:"score" bson:"score"`
	CatId    primitive.ObjectID `jx:"catId" json:"catId" bson:"catId"`
	Cat      *DemoCat           `jx:"cat" json:"cat" bson:"cat"`
	CreateAt *time.Time         `json:"createAt" bson:"createAt"`
	UpdateAt *time.Time         `json:"updateAt" bson:"updateAt"`
	DeleteAt *time.Time         `json:"deleteAt" bson:"deleteAt"`
}

func NewDemo() *Demo {
	return &Demo{}
}

func (this *Demo) DocGetId() primitive.ObjectID {
	return this.Id
}
func (this *Demo) DocSetId(id string) {
	this.Id, _ = primitive.ObjectIDFromHex(id)
}
func (this *Demo) DocGetName() string {
	return "jxcore_demo"
}
func (this *Demo) DocGetFactory() *mgorm.Factory {
	factory := mgorm.NewFactory()
	factory.Db = core.DBMongo
	factory.Doc = this
	return factory
}
func (this *Demo) Create() error {
	return this.DocGetFactory().Create(this)
}
func (this *Demo) Replace() error {
	return this.DocGetFactory().Replace(this)
}
func (this *Demo) Save() error {
	now := time.Now()
	if this.Id.IsZero() {
		this.CreateAt = &now
		this.UpdateAt = &now
		return this.DocGetFactory().Create(this)
	} else {
		this.UpdateAt = &now
		return this.DocGetFactory().Replace(this)
	}
}
func (this *Demo) Delete() error {
	return this.DocGetFactory().Delete(this)
}
func (this *Demo) UnDelete() error {
	return this.DocGetFactory().UnDelete(this)
}
func (this *Demo) Destroy() error {
	return this.DocGetFactory().Destroy(this)
}
func (this *Demo) Update(obj ss.Obj) error {
	return this.DocGetFactory().Update(this, obj)
}
func (this *Demo) Serialize() ([]byte, error) {
	return core.Json().Marshal(this)
}
func (this *Demo) Deserialize(data []byte) error {
	return core.Json().Unmarshal(data, this)
}

type DemoCrud struct {
	Doc     *Demo
	Factory *mgorm.Factory
}

var CrudDemo DemoCrud

func NewDemoCrud() *DemoCrud {
	doc := NewDemo()
	return &DemoCrud{
		Doc:     doc,
		Factory: doc.DocGetFactory(),
	}
}

func (this *DemoCrud) FindById(id string) (*Demo, error) {
	doc := &Demo{}
	err := this.Factory.FindId(doc, id)
	return doc, err
}
func (this *DemoCrud) FindOneBy(filter ss.Obj, orders ss.ArrayString) (*Demo, error) {
	doc := &Demo{}
	err := this.Factory.FindOneBy(doc, &mgorm.Query{
		Filters: filter,
		Order:   orders,
	})
	return doc, err
}
func (this *DemoCrud) FindManyBy(filter ss.Obj, orders ss.ArrayString, page int, size int) ([]*Demo, error) {
	docs := make([]*Demo, 0)
	err := this.Factory.FindManyBy(&docs, &mgorm.Query{
		Filters: filter,
		Order:   orders,
		Page:    page,
		Size:    size,
	})
	return docs, err
}
func (this *DemoCrud) UpdateBy(filter, updater ss.Obj) (int64, error) {
	return this.Factory.UpdateManyBy(updater, &mgorm.Query{
		Filters: filter,
	})
}
func (this *DemoCrud) DeleteBy(filter ss.Obj) (int64, error) {
	return this.Factory.DeleteManyBy(&mgorm.Query{
		Filters: filter,
	})
}
func (this *DemoCrud) DestroyBy(filter ss.Obj, all bool) (int64, error) {
	if !all && len(filter) == 0 {
		return 0, errors.New("NoneLimitedDelete")
	}
	return this.Factory.DestroyManyBy(&mgorm.Query{
		Filters: filter,
	})
}
func (this *DemoCrud) Count(obj ss.Obj) (int64, error) {
	return this.Factory.Count(&mgorm.Query{
		Filters: obj,
	})
}
func (this *DemoCrud) SumInt(obj ss.Obj, field string) (int64, error) {
	return this.Factory.AggregateSumInt(&mgorm.Query{
		Filters: obj,
	}, field)
}
func (this *DemoCrud) SumFloat(obj ss.Obj, field string) (float64, error) {
	return this.Factory.AggregateSumFloat(&mgorm.Query{
		Filters: obj,
	}, field)
}
